<template>
  <view
    class="fixed zIndex-12 flex"
    :style="[
      BtnPos == 'tl'
        ? { transform: `translateX(${_offset[0]}rpx) translateY(${_offset[1]}rpx)` }
        : '',
      BtnPos == 'tr'
        ? {
            transform: `translateX(-${_offset[0]}rpx) translateY(${_offset[1]}rpx)`,
            right: '0px',
          }
        : '',
      BtnPos == 'tc'
        ? { transform: `translateX(${centerPosLeft}px) translateY(${_offset[1]}rpx)` }
        : '',
      BtnPos == 'bl'
        ? {
            transform: `translateX(${_offset[0]}rpx) translateY(-${_offset[1]}rpx)`,
            bottom: '0px',
          }
        : '',
      BtnPos == 'br'
        ? {
            transform: `translateX(-${_offset[0]}rpx) translateY(-${_offset[1]}rpx)`,
            right: '0px',
            bottom: '0px',
          }
        : '',
      BtnPos == 'bc'
        ? {
            transform: `translateX(${centerPosLeft}px) translateY(-${_offset[1]}rpx)`,
            bottom: '0px',
          }
        : '',
      !isH5 && (BtnPos == 'tl' || BtnPos == 'tc' || BtnPos == 'tr') ? { top: '0px' } : '',
      parent_style,
    ]"
  >
    <!-- 主按钮 -->
    <view
      :style="[{ width: props.width + 'rpx', height: props.height + 'rpx' }]"
      class="flex-center"
    >
      <tm-sheet :transprent="true" :padding="[0, 0]" :margin="[0, 0]" :color="_btn.color">
        <slot>
          <tm-button
            :followTheme="props.followTheme"
            @click="onclick"
            _class="flex flex-col flex-col-center-center"
            :shadow="3"
            :linear="_btn.linear"
            :linear-deep="_btn.linearDeep"
            :color="_btn.color"
            :margin="[0, 0]"
            :round="16"
            :padding="[0, 0]"
            :width="props.width - 12"
            :height="props.height - 12"
          >
            <view class="flex flex-col flex-col-center-center">
              <tm-icon
                :userInteractionEnabled="false"
                :follow-dark="false"
                :color="_btn.fontColor"
                :name="_btn.icon"
                :font-size="_btn.iconSize"
              ></tm-icon>
              <tm-text
                :userInteractionEnabled="false"
                :follow-dark="false"
                :color="_btn.fontColor"
                v-if="_btn.label"
                :label="_btn.label"
                :font-size="_btn.fontSize"
              ></tm-text>
            </view>
          </tm-button>
        </slot>
      </tm-sheet>
    </view>
    <!-- 子菜单 -->
    <view
      :userInteractionEnabled="showActions"
      v-if="_actionsItem.length > 0 && showActions"
      class="absolute flex"
      :style="[AcionPos_xy]"
    >
      <view
        :style="[{ width: props.width + 'rpx', height: props.height + 'rpx' }]"
        class="flex-center"
      >
        <tm-sheet
          :followTheme="props.followTheme"
          @click="change(index, item)"
          v-for="(item, index) in _actionsItem"
          :key="index"
          _class="flex flex-col flex-col-center-center"
          :round="16"
          :shadow="2"
          :linear="item.linear"
          :linear-deep="item.linearDeep"
          :color="item.color"
          :margin="[0, 0]"
          :padding="[0, 0]"
          :width="props.width - 12"
          :height="props.height - 12"
        >
          <tm-icon
            :userInteractionEnabled="false"
            :color="item.fontColor"
            :name="item.icon"
            :font-size="item.iconSize"
          ></tm-icon>
          <tm-text
            :userInteractionEnabled="false"
            :color="item.fontColor"
            v-if="item.label"
            :label="item.label"
            :font-size="item.fontSize"
          ></tm-text>
        </tm-sheet>
      </view>
    </view>
  </view>
</template>
<script lang="ts" setup>
/**
 * 悬浮按钮
 * @description 总共6个位置，每个位置有四方向的子按钮展开位置，一共24个位置可控制。具体看文档。
 * @example <tm-floatButton :btn="{icon:'tmicon-plus',linear:'top'}"></tm-floatButton>
 * @method click 主按钮被点击，(e:Event)
 * @method change  子按钮被点击， (index:number,item:actionsItem)
 */
import { computed, PropType, ref, inject } from "vue";
import { positionType, popDir, actionsItem } from "./interface";
import tmSheet from "../tm-sheet/tm-sheet.vue";
import tmIcon from "../tm-icon/tm-icon.vue";
import tmText from "../tm-text/tm-text.vue";
import tmButton from "../tm-button/tm-button.vue";
/**
 * 事件说明
 * click：主按钮被点击，
 * change :子按钮被点击，
 */
const emits = defineEmits(["click", "change"]);
const props = defineProps({
  followTheme: {
    type: [Boolean, String],
    default: true,
  },
  //主按钮的位置
  position: {
    type: String as PropType<positionType>,
    default: "br",
    validator: (val: string) => {
      let isv = ["bc", "bl", "br", "tc", "tl", "tr"].includes(val);
      if (!isv) {
        console.error("位置参数为:'bc','bl','br','tc','tl','tr'其中的一项");
      }
      return isv;
    },
  },
  //子菜单弹出的位置
  actionsPos: {
    type: String as PropType<popDir>,
    default: "top",
    validator: (val: string) => {
      let isv = ["left", "right", "top", "bottom"].includes(val);
      if (!isv) {
        console.error("位置参数为:'left','right','top','bottom'其中的一项");
      }
      return isv;
    },
  },
  width: {
    type: Number,
    default: 112,
  },
  height: {
    type: Number,
    default: 112,
  },
  offset: {
    type: Array as PropType<Array<number>>,
    default: () => [32, 32],
  },
  //子按钮组数据
  actions: {
    type: Array as PropType<Array<actionsItem>>,
    default: () => [],
  },
  // 主按钮对象数据
  btn: {
    type: Object as PropType<actionsItem>,
    default: () => {},
    required: true,
  },
  //是否默认显示子菜单
  showActions: {
    type: Boolean,
    default: false,
  },
  //点击子菜单后，是否需要隐藏，如果为false,点击子按钮后不会隐藏按钮。始终保持展开子按钮。
  clickHidnActions: {
    type: Boolean,
    default: true,
  },
  disabledScrollTo: {
    type: Boolean,
    default: true,
  },
  scrollTo: {
    type: Object as PropType<{ scrollTop: number; selector: string; duration: number }>,
    default: () => {
      return {
        scrollTop: 0,
        selector: "",
        duration: 300,
      };
    },
  },
});

const sysinfo = inject(
  "tmuiSysInfo",
  computed(() => {
    return {
      bottom: 0,
      height: 750,
      width: uni.upx2px(750),
      top: 0,
      isCustomHeader: false,
      sysinfo: null,
    };
  })
);
const windowWidth = computed(() => sysinfo.value.width);
const windowTop = computed(() => sysinfo.value.top);

const isH5 = ref(false);
// #ifdef H5
isH5.value = true;
// #endif
const showActions = ref(props.showActions ?? false);
const BtnPos = computed(() => props.position);
const AcionPos = computed(() => props.actionsPos);
const _offset = computed(() => {
  let ost = props.offset ?? [0, 0];
  // #ifdef APP-NVUE
  ost = [uni.upx2px(props.offset[0]), uni.upx2px(props.offset[1])];
  // #endif
  return ost;
});
const centerPosLeft = computed(() => {
  let ps =
    (windowWidth.value - uni.upx2px(props.width * 1.5)) / 2 +
    uni.upx2px(_offset.value[0]);
  // #ifndef APP-NVUE
  ps =
    (windowWidth.value - uni.upx2px(props.width * 2)) / 2 + uni.upx2px(_offset.value[0]);
  // #endif
  return ps;
});
const _btn = computed(() => {
  return {
    icon: "tmicon-plus",
    fontSize: 20,
    color: "primary",
    linear: "",
    linearDeep: "accent",
    label: "",
    iconSize: 42,
    fontColor: "",
    ...(props.btn ?? {}),
  };
});
const _actionsItem = computed(() => {
  let asbtn = props.actions.map((el) => {
    let default_btn: actionsItem = {
      icon: "tmicon-plus",
      fontSize: 20,
      color: "primary",
      linear: "",
      linearDeep: "accent",
      label: "",
      fontColor: "",
      iconSize: 36,
    };
    return { ...default_btn, ...el };
  });
  return asbtn;
});
const AcionPos_xy = computed(() => {
  if (
    (BtnPos.value == "tl" ||
      BtnPos.value == "tr" ||
      BtnPos.value == "tc" ||
      BtnPos.value == "bc") &&
    AcionPos.value == "bottom"
  ) {
    return {
      top: `${props.height}rpx`,
      height: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "column",
    };
  }
  if ((BtnPos.value == "bl" || BtnPos.value == "br") && AcionPos.value == "bottom") {
    return {
      top: `${props.height}rpx`,
      height: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "column",
    };
  }
  if ((BtnPos.value == "bl" || BtnPos.value == "br") && AcionPos.value == "top") {
    return { top: `0px`, dispaly: "flex", "flex-direction": "column-reverse" };
  }
  if (
    (BtnPos.value == "tl" ||
      BtnPos.value == "tr" ||
      BtnPos.value == "tc" ||
      BtnPos.value == "bc") &&
    AcionPos.value == "top"
  ) {
    return {
      top: `-0rpx`,
      height: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "column",
    };
  }
  if (
    (BtnPos.value == "tl" ||
      BtnPos.value == "tc" ||
      BtnPos.value == "bl" ||
      BtnPos.value == "br" ||
      BtnPos.value == "bc") &&
    AcionPos.value == "right"
  ) {
    return {
      left: `${props.height}rpx`,
      width: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "row",
    };
  }
  if (
    (BtnPos.value == "tl" ||
      BtnPos.value == "tr" ||
      BtnPos.value == "tc" ||
      BtnPos.value == "bl" ||
      BtnPos.value == "br" ||
      BtnPos.value == "bc") &&
    AcionPos.value == "left"
  ) {
    return {
      right: `${props.height}rpx`,
      width: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "tr" && AcionPos.value == "right") {
    return {
      right: `${0}rpx`,
      width: props.actions.length * props.height + "rpx",
      dispaly: "flex",
      "flex-direction": "row",
    };
  }
});
const parent_style = computed(() => {
  let height_width = showActions.value
    ? (props.actions.length + 1) * props.height
    : props.height;
  //原生应用，如果控制高度再显示子按钮， 会有闪烁。因此不需要控制。
  // #ifdef APP-PLUS-NVUE
  height_width = (props.actions.length + 1) * props.height;
  // #endif

  if (
    (BtnPos.value == "tl" || BtnPos.value == "tr" || BtnPos.value == "tc") &&
    AcionPos.value == "bottom"
  ) {
    return { height: height_width + "rpx" };
  }
  if (BtnPos.value == "tl" && AcionPos.value == "top") {
    let top = -(props.actions.length * props.height - _offset.value[1]);
    // #ifdef APP-NVUE
    top = -props.height + _offset.value[1];
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(${_offset.value[0]}rpx) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }

  if ((BtnPos.value == "tl" || BtnPos.value == "tc") && AcionPos.value == "right") {
    return { width: height_width + "rpx" };
  }
  if (BtnPos.value == "tl" && AcionPos.value == "left") {
    let left = -(props.actions.length * props.height - _offset.value[0]);
    // #ifdef APP-NVUE
    left = -props.height + _offset.value[0];
    // #endif
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}rpx) translateY(${_offset.value[1]}rpx)`,
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "tr" && AcionPos.value == "left") {
    let left = -(props.actions.length * props.height - _offset.value[0]);
    // #ifdef APP-NVUE
    left = -props.height + _offset.value[0];
    // #endif
    return {
      width: height_width + "rpx",
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "tr" && AcionPos.value == "top") {
    let top = -(props.actions.length * props.height - _offset.value[1]);
    // #ifdef APP-NVUE
    // top = -props.height +  _offset.value[1]
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(-${_offset.value[0]}rpx) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }
  if (BtnPos.value == "tr" && AcionPos.value == "right") {
    let right = props.actions.length * props.height - _offset.value[0];
    // #ifdef APP-NVUE
    // right = props.height -  _offset.value[0]
    // #endif
    return {
      width: height_width + "rpx",
      transform: `translateX(${right}rpx) translateY(${_offset.value[1]}rpx)`,
    };
  }
  if (BtnPos.value == "tc" && AcionPos.value == "left") {
    let left =
      centerPosLeft.value -
      uni.upx2px(props.actions.length * props.height) -
      uni.upx2px(_offset.value[0]);
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${_offset.value[1]}rpx)`,
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "tc" && AcionPos.value == "top") {
    let left = centerPosLeft.value + uni.upx2px(_offset.value[0]);
    let top = -(props.actions.length * props.height - _offset.value[1]);
    // #ifdef APP-NVUE
    // top = -props.height +  _offset.value[1]
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }
  if (BtnPos.value == "bl" && AcionPos.value == "bottom") {
    let top = props.actions.length * props.height - _offset.value[1];
    // #ifdef APP-NVUE
    top = props.height - _offset.value[1];
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(${_offset.value[0]}rpx) translateY(${top}rpx)`,
    };
  }
  if (BtnPos.value == "bl" && AcionPos.value == "top") {
    let top = -_offset.value[1];
    return {
      height: height_width + "rpx",
      transform: `translateX(${_offset.value[0]}rpx) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }
  if (BtnPos.value == "bl" && AcionPos.value == "right") {
    return {
      width: height_width + "rpx",
    };
  }
  if (BtnPos.value == "bl" && AcionPos.value == "left") {
    let left = -(props.actions.length * props.height - _offset.value[0]);
    // #ifdef APP-NVUE
    left = -props.height + _offset.value[0];
    // #endif
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}rpx) translateY(${-_offset.value[1]}rpx)`,
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "br" && AcionPos.value == "bottom") {
    let top = props.actions.length * props.height - _offset.value[1];
    // #ifdef APP-NVUE
    top = props.height - _offset.value[1];
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(${-_offset.value[0]}rpx) translateY(${top}rpx)`,
    };
  }
  if (BtnPos.value == "br" && AcionPos.value == "top") {
    let top = -_offset.value[1];
    return {
      height: height_width + "rpx",
      transform: `translateX(${-_offset.value[0]}rpx) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }
  if (BtnPos.value == "br" && AcionPos.value == "right") {
    let right = props.actions.length * props.height - _offset.value[0];
    // #ifdef APP-NVUE
    right = props.height - _offset.value[0];
    // #endif
    return {
      width: height_width + "rpx",
      transform: `translateX(${right}rpx) translateY(${-_offset.value[1]}rpx)`,
    };
  }
  if (BtnPos.value == "br" && AcionPos.value == "left") {
    let left = -_offset.value[0];
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}rpx) translateY(${-_offset.value[1]}rpx)`,
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "bc" && AcionPos.value == "left") {
    let left =
      centerPosLeft.value -
      uni.upx2px(props.actions.length * props.height) -
      uni.upx2px(_offset.value[0]);
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${-_offset.value[1]}rpx)`,
      "flex-direction": "row-reverse",
    };
  }
  if (BtnPos.value == "bc" && AcionPos.value == "right") {
    let left = centerPosLeft.value + uni.upx2px(_offset.value[0]);
    return {
      width: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${-_offset.value[1]}rpx)`,
      "flex-direction": "row",
    };
  }
  if (BtnPos.value == "bc" && AcionPos.value == "top") {
    let left = centerPosLeft.value + uni.upx2px(_offset.value[0]);
    let top = -_offset.value[1];
    return {
      height: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${top}rpx)`,
      "flex-direction": "column-reverse",
    };
  }
  if (BtnPos.value == "bc" && AcionPos.value == "bottom") {
    let left = centerPosLeft.value + uni.upx2px(_offset.value[0]);
    let top = props.actions.length * props.height + _offset.value[1];
    // #ifdef APP-NVUE
    top = props.height - _offset.value[1];
    // #endif
    return {
      height: height_width + "rpx",
      transform: `translateX(${left}px) translateY(${top}rpx)`,
      "flex-direction": "column",
    };
  }
});

function onclick(e: any) {
  if (props.clickHidnActions) {
    showActions.value = !showActions.value;
  } else {
    showActions.value = true;
  }
  emits("click", e);
  // #ifndef APP-NVUE
  if (!props.disabledScrollTo) {
    uni.pageScrollTo({
      scrollTop: props.scrollTo.scrollTop,
      duration: props.scrollTo.duration,
      selector: props.scrollTo.selector,
    });
  }
  // #endif
}
function change(index: number, item: actionsItem) {
  if (props.clickHidnActions) {
    showActions.value = false;
  }
  emits("change", index, item);
}
</script>
